/*
 * =====================================================================================
 *
 *       Filename:  watcher.cpp
 *
 *    Description:   监控类的实现
 *
 *        Version:  0.1
 *        Created:  2011年03月24日 17时36分47秒
 *        Updated:  2011年04月26日 19时17分19秒
 *
 *      Copyright: lgy
 *       Compiler:  gcc
 *
 *         Author: lgy
 *         School:  ssdut
 *
 * =====================================================================================
 */

#include "watcher.h"
/*
  函数功能：将一个文件描述符设置成非阻塞的形势
  参数：int，文件描述符值
*/
void setnonblocking(int sock)
{
    int opts;
    opts=fcntl(sock,F_GETFL);
    if(opts<0)
    {
        perror("fcntl(sock,GETFL)");
        exit(1);
    }
    opts = opts|O_NONBLOCK;
    if(fcntl(sock,F_SETFL,opts)<0)
    {
        perror("fcntl(sock,SETFL,opts)");
        exit(1);
    }
}
/*
  构造函数，没有参数，已经被废弃
*/
watcher::watcher()
{
    hasUpdated=0;
    QString DirName;
    if((fd=inotify_init())<0)                 //初始化监控事件，获得文件描述符
    {
        perror("failed to init inotify");
        exit(1);
    }
    setnonblocking(fd);                       //设置成非阻塞
    QFile file("./setting");
    if(file.open(QFile::ReadOnly))
    {
        QTextStream in(&file);
        in>>DirName;
    }
    tsf_sock=0;
    file.close();
    addDir(DirName.toStdString());              //添加监控文件夹，用指定的某个文件夹初始化
}
/*
  带参构造函数
  dirName：监控目录
  argSocketFd：控制tcp的文件描述符
  argUserName：用户明
  */
watcher::watcher(string dirName, int argSocketFd, string argUserName,long useage)
{
    hasUpdated=0;
    Running=1;
    isSendingData=0;
    isUpdating=0;
    isMoveIning=0;
    useAge=useage;
    ctl_sock=argSocketFd;
    tsf_sock=0;
    userName=argUserName;
    workDir=QString(dirName.c_str());
    if((fd=inotify_init())<0)                 //初始化监控事件，获得文件描述符
    {
        perror("failed to init inotify");
        exit(1);
    }
    setnonblocking(fd);                       //设置成非阻塞
    addDir(dirName);              //添加监控文件夹，用指定的某个文件夹初始化
}

/*
  返回值：string，wd值对应的文件夹名字
  参数：int，wd值
*/
string watcher::getdirOnwd(int wd)
{
    return watchers[wd];
}
int watcher::getwd(string a)
{
    for(map<int,string>::iterator it=watchers.begin();it!=watchers.end();it++)
    {
        if(Running==0)
            break;
        if(it->second==a)
            return it->first;
    }
    return 0;
}

/*
  监控函数
*/
void watcher::watch()
{
    int i=0;
    int res;
    while(Running)
    {
        timer.tv_sec=0;
        timer.tv_usec=500000;                        //设置超时时间
        FD_ZERO(&fdset);                             //初始化文件描述符集
        FD_SET(fd,&fdset);                           //设置fd在文件描述符集中
        res=select(fd+1,&fdset,NULL,NULL,&timer);    //利用select函数对监控时间的文件描述符进行等待，知道该文件描述符可读或者超时
        if(res==1)                                   //如果返回是1，表示改文件描述符可读，可读取其中的事件信息
        {
            if((res=read(fd,buff,buf_len))<0)
            {
                continue;
            }
            while(i<res&&Running)                             //对一次读取的信息进行处理
            {
                struct inotify_event* event=(struct inotify_event*)&buff[i];
                if(event->len)
                {
                    string tmpname=string(event->name);
                    //过滤事件，过滤掉vim和emacs中的临时事件信息以及version文件
                    if(tmpname.find_first_of('.')!=0)
                    {
                        int tmpt=event->mask;
                        int tmpwd=event->wd;
                        int tmpcookie=event->cookie;
                        //将获得的信息新建成一个ievent对象，并将该对象压入过滤处理队列中
                        tmpname=watchers[tmpwd]+'/'+tmpname;
                        ievent* ie=new ievent(tmpname,tmpt,tmpwd,tmpcookie);
                        fliterlist.push_back(ie);
                    }
                }
                i+=event_size + event->len;
            }
            i=0;
        }
        else if(res==0)          //如果是0，表示是超时，也就是说这段时间内没有发生事件，则对上一段时间产生的时间进行处理
        {
            fliter();
        }
        else
        {
            cout<<"select error"<<endl;
        }
    }
}
/*
  时间过滤和处理函数
*/
void watcher::fliter()
{
    ievent* event=NULL;
    int deleteflag=1;

    while(!fliterlist.empty()&&Running)                      //处理事件
    {
        event=fliterlist.front();
        fliterlist.pop_front();
        if(event->type & IN_CREATE)
        {
            process();                              //处理processlist中的事件，保证事件处理顺序正常
            if(event->type & IN_ISDIR)              //创建事件
            {
                //如果是文件夹被创建，判断是否文件夹为空（不为空说明是从不同的盘符移动过来的，要进行处理）SIZE
                if(!isEmptyDir(event->source))
                {
//                    long tmpSize=this->countSizeForDir(event->source.c_str());
//                    if((tmpSize+useAge)<=USER_SIZE)
//                    {
                        cout<<"move in"<<endl;
                        isUpdating=1;
                        isMoveIning=1;
                        isSendingData=1;
                        emit this->setEmblemUpdating();
                        //在这里判断文件夹大小，如果过大的话就不进行处理了，然后给该文件夹打上叉
                        moveInDir(event->source,event->_wd);


                        for(QList<QString>::iterator it=fileToUpdate.begin();it!=fileToUpdate.end();it++)
                        {
                            if(Running==0)
                                break;
                            ctl_update(CREATE_F,(*it).toStdString());
                            this->data_update(*it);
                            this->rmFromIconMap(*it);
                        }
                        fileToUpdate.clear();
                        isSendingData=0;
                        isMoveIning=0;
                        isUpdating=0;
//                        useAge+=tmpSize;
//                        emit this->sizeChanged(useAge);
                        emit this->setEmblemUpdated();
//                    }
//                    else
//                    {
//                        this->setIconUpdateFailed(QString(event->source.c_str()));
//                    }
                }
                else
                {
                    //创建文件夹，要给size加上4096，判断是否过大，超大的话，就不进行操作，并且给文件夹打叉SIZE
//                    long tmpSize=this->countSizeForDir(event->source.c_str());
//                    if((tmpSize+useAge)<=USER_SIZE)
//                    {
                        ctl_update(CREATE_D,event->source);
                        string temp_name=event->source;
                        if((wd=inotify_add_watch(fd,temp_name.c_str(),
                                                 IN_CREATE|IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE|IN_CLOSE_WRITE))<0)
                        {
                            perror("failed to add inotify watcher");
                            exit(1);
                        }
                        watchers[wd]=temp_name;
//                        useAge+=tmpSize;
//                        emit sizeChanged(useAge);
//                    }
//                    else
//                    {
//                        this->setIconUpdateFailed(QString(event->source.c_str()));
//                    }
                }
            }
            else
            {
                //文件被创建的时候并不去上传文件，等到修改事件发生再去上传文件
                ctl_update(CREATE_F,event->source);
                //考虑是否要在这里添加监视SIZE
                //data_update(event->source.c_str());
            }
        }
        if(event->type & IN_CLOSE_WRITE||event->type & IN_MODIFY)  //修改事件
        {
            cout<<"modify"<<event->source<<endl;
            process();                              //处理processlist中的事件，保证事件处理顺序正常
            //判断修改后的文件大小是否过大，过大的话不进行处理，给文件打叉SIZE
            if(event->type & IN_ISDIR)
            {
//                useAge=this->countSizeForDir(this->workDir.toStdString().c_str());
//                if(useAge<=USER_SIZE)
//                {
                    ctl_update(UP_D,event->source);
//                    emit sizeChanged(useAge);
//                }
//                else
//                {
//                   this->setIconUpdateFailed(QString(event->source.c_str()));
//                }
            }
            else
            {
//                useAge=this->countSizeForDir(this->workDir.toStdString().c_str());
//                cout<<"modify"<<useAge<<endl;
//                if(useAge<=USER_SIZE)
//                {
                    isSendingData=1;
                    data_update(QString(event->source.c_str()));
                    isSendingData=0;
//                    emit sizeChanged(useAge);
//                }
//                else
//                {
//                   this->setIconUpdateFailed(QString(event->source.c_str()));
//                }
            }
        }
        if(event->type & IN_MOVED_FROM)       //如果是移出操作，先压栈
        {
            //考虑一下在什么地方删除文件大小SIZE
            processlist.push_back(event);
            if(deleteflag==1)
                deleteflag=0;
        }
        if(event->type & IN_MOVED_TO)         //移入操作，先压栈
        {
            processlist.push_back(event);
            if(deleteflag==1)
                deleteflag=0;
        }
        if(event->type & IN_DELETE)           //删除操作
        {
            if(processlist.empty())           //处理栈空，把删除事件压栈
                processlist.push_back(event);
            else if(!(processlist.back()->type&IN_DELETE))
                processlist.push_back(event);
            else if(event->type&IN_ISDIR)     //如果删除的是文件夹
            {
                string pdir=event->source;
                if(pdir==watchers[processlist.back()->_wd])     //如果现在要删除的是之前删除的文件或文件夹的父目录
                {
                    //将是当前删除的文件夹的子文件的删除事件弹栈，将删除当前文件夹时间压栈
                    while((!processlist.empty())&&(pdir==watchers[processlist.back()->_wd])&&(event->type&IN_DELETE)&&Running)
                    {
                        delete processlist.back();
                        processlist.pop_back();
                    }
                    processlist.push_back(event);
                }
                else
                {
                    processlist.push_back(event);
                }
            }
            else
            {
                processlist.push_back(event);
            }
            if(deleteflag==1)
                deleteflag=0;
        }
    }
    process();
    if(deleteflag==1)
    {
        if(event!=NULL)
            delete event;
    }
}
/*
  对一个文件夹及其子文件夹递归添加监控
  参数：string，文件夹名称
*/
void watcher::addDir(string dirname)
{
    DIR* pdir;
    struct dirent *dir;
    pdir=opendir(dirname.c_str());
    if((wd=inotify_add_watch(fd,dirname.c_str(),
                             IN_CREATE|IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE|IN_CLOSE_WRITE))<0)
    {
        perror("failed to add inotify watcher");
        exit(1);
    }
    watchers[wd]=dirname;
    while((dir=readdir(pdir))!=NULL&&Running)
    {
        if(dir->d_type&DT_DIR)
        {
            if(strcmp(dir->d_name,".")==0||strcmp(dir->d_name,"..")==0)
                continue;
            string temp=dirname+'/'+dir->d_name;
            addDir(temp);
        }
    }
    closedir(pdir);
}


/*
  对移入文件夹及其子文件夹递归处理
  参数：string，文件夹名称
*/
void watcher::moveInDir(string dirname,int pwd)
{
    DIR* pdir;
    struct dirent *dir;
    int tmptype=0;
    pdir=opendir(dirname.c_str());
    if((wd=inotify_add_watch(fd,dirname.c_str(),
                             IN_CREATE|IN_MODIFY|IN_MOVED_FROM|IN_MOVED_TO|IN_DELETE|IN_CLOSE_WRITE))<0)
    {
        perror("failed to add inotify watcher");
        exit(1);
    }
//    tmptype=IN_ISDIR|IN_CREATE;
//    ievent* event=new ievent(dirname,tmptype,pwd);
//    fliterlist.push_back(*event);
    ctl_update(CREATE_D,dirname);
    watchers[wd]=dirname;
    while((dir=readdir(pdir))!=NULL&&Running)
    {
        if(dir->d_type&DT_DIR)
        {
            if(strcmp(dir->d_name,".")==0||strcmp(dir->d_name,"..")==0)
                continue;
            string temp=dirname+'/'+dir->d_name;
            moveInDir(temp,wd);
        }
        else
            {
            string tmp=dirname+'/'+dir->d_name;
//            tmptype=IN_CREATE;
//            ievent* event=new ievent(tmp,tmptype,pwd);
//            fliterlist.push_back(*event);
//            ctl_update(CREATE_F,tmp);
//            data_update(QString(tmp.c_str()));
            fileToUpdate.push_back(QString(tmp.c_str()));
            this->SearchFile(QString(tmp.c_str()));
        }
    }
    closedir(pdir);
}

/*
  处理processlist中的删除和移动事件
*/

void watcher::process()
{
    ievent* event;
    while(!processlist.empty()&&Running)           //处理被压栈的事件
    {
        event=processlist.front();
        processlist.pop_front();
        if(event->type&IN_DELETE)
        {
            if(event->type&IN_ISDIR)  //将删除事件弹栈
            {
                //删除整个文件夹的大小SIZE
                ctl_update(DEL_D,event->source);
                /*	string tmp=watchers[event->_wd]+'/'+event->source;
                        int tmpwd=getwd(tmp);
                        cout<<tmpwd<<endl;
                        if(inotify_rm_watch(fd,tmpwd)<0)
                        perror("rm error\n");*/
                useAge=this->countSizeForDir(workDir.toStdString().c_str());
                emit sizeChanged(useAge);
            }
            else
            {
                ctl_update(DEL_F,event->source);
                useAge=this->countSizeForDir(workDir.toStdString().c_str());
                emit sizeChanged(useAge);
            }
            delete event;
        }
        else if(event->type&IN_MOVED_TO)         //移入事件
        {
            if(event->type&IN_ISDIR)             //移入一个文件夹的操作
            {
                //判断移入文件夹的大小，过大的话则不进行处理，打叉
//                long tmpSize=this->countSizeForDir(event->source.c_str());
//                if((useAge+tmpSize)<=USER_SIZE)
//                {
                    string dirname=event->source;

                    isUpdating=1;
                    isMoveIning=1;
                    isSendingData=1;
                    emit this->setEmblemUpdating();
                    moveInDir(dirname,event->_wd);                 //递归添加监控



                    for(QList<QString>::iterator it=fileToUpdate.begin();it!=fileToUpdate.end();it++)
                    {
                        if(Running==0)
                            break;
                        ctl_update(CREATE_F,(*it).toStdString());
                        this->data_update(*it);
                        this->rmFromIconMap(*it);
                    }
                    fileToUpdate.clear();
                    isSendingData=0;
                    isMoveIning=0;
                    isUpdating=0;
                    emit this->setEmblemUpdated();
//                    useAge+=tmpSize;
//                    emit sizeChanged(useAge);
//                }
//                else
//                {
//                    this->setIconUpdateFailed(QString(event->source.c_str()));
//                }
            }
            else
            {
//                long tmpSize=this->countSizeForFile(event->source.c_str());
//                if((useAge+tmpSize)<=USER_SIZE)
//                {
                    ctl_update(CREATE_F,event->source);
                    isSendingData=1;
                    data_update(QString(event->source.c_str()));
                    isSendingData=0;
//                    useAge+=tmpSize;
//                    cout<<"move in file"<<useAge<<endl;
//                    emit sizeChanged(useAge);
//                }
//                else
//                {
//                    this->setIconUpdateFailed(QString(event->source.c_str()));
//                }
            }
            delete event;
        }
        else if(event->type&IN_MOVED_FROM)
        {
            if(processlist.empty())              //移出操作。判断是否是监控文件夹内部的移动
            {
                if(event->type&IN_ISDIR)
                    ctl_update(DEL_D,event->source);
                else
                    ctl_update(DEL_F,event->source);
                delete event;
                useAge=this->countSizeForDir(workDir.toStdString().c_str());
                emit sizeChanged(useAge);
            }

            else if((processlist.front()->type
                     &IN_MOVED_TO)&&(processlist.front()->cookie==event->cookie))   //是内部移动，相当于一个重命名事件
            {
                if(event->type&IN_ISDIR)
                {
                    ctl_update(MOVE,event->source,processlist.back()->source);
                    //修改监控文件夹中wd对应的文件夹名称
                    string oldDirname=event->source;
                    string newDirname=processlist.back()->source;
                    watchers[getwd(oldDirname)]=newDirname;
                }
                else
                    ctl_update(MOVE,event->source,processlist.back()->source);
                delete event;
                delete processlist.front();
                processlist.pop_front();
            }
            else
            {
                if(event->type&IN_ISDIR)
                    ctl_update(DEL_D,event->source);
                else
                    ctl_update(DEL_F,event->source);
                delete event;
                useAge=this->countSizeForDir(workDir.toStdString().c_str());
                emit sizeChanged(useAge);
            }
        }
    }
}

/*
  判断一个文件夹是否为空
*/
bool watcher::isEmptyDir(string dirname)
{
    DIR* pdir;
    int tmp=0;
    struct dirent *dir;
    pdir=opendir(dirname.c_str());
    while((dir=readdir(pdir))!=NULL&&Running)
    {
        if(dir->d_type&DT_DIR)
        {
            if(strcmp(dir->d_name,".")==0||strcmp(dir->d_name,"..")==0)
                continue;
            else
                tmp++;
        }
        else tmp++;
    }
    closedir(pdir);
    if(tmp==0)
        return 1;
    else
        return 0;
}

int watcher::ctl_update( uint8_t type, const string& path1,  const string& path2)
{
        //打包

        emit this->setEmblemUpdating();
        int8_t reply;
        cout<<int(type)<<endl;
        //如果是移动事件
        if(type==MOVE)
        {
                //获取第一个文件名字
                 QString dir(path1.c_str());
                 dir.remove(workDir);
                 QString serverDir(userName.c_str());
                 serverDir.prepend("/gsync/");
                 serverDir+=dir;
                ctl_pkg_t info;
                info.type = type;


                snprintf(info.str.path, PATH_LEN,serverDir.toStdString().c_str());


                //把包发给服务器
                Writen(ctl_sock,&info,sizeof(info));

                //获取第二个文件名字
            QString dir2(path2.c_str());
            dir2.remove(workDir);
            QString serverDir2(userName.c_str());
            serverDir2.prepend("/gsync/");
            serverDir2+=dir2;
            snprintf(info.str.path, PATH_LEN,serverDir2.toStdString().c_str());
            Writen(ctl_sock,&info,sizeof(info));




            if(readn(ctl_sock,&reply,sizeof(int8_t)) < 0)
                perror("read");



            if(reply<0)
            {
                perror("服务器未接受到信息");
            }
            else
            {
                if(fliterlist.empty()&&processlist.empty()&&isMoveIning==0)
                {
                    isUpdating=0;
                    emit this->setEmblemUpdated();
                }
                if(isMoveIning==0)
                this->EmblemUpdated(QString(path2.c_str()));
            }
        }
        else
        {
            QString dir(path1.c_str());
            dir.remove(workDir);
            QString serverDir(userName.c_str());
            serverDir.prepend("/gsync/");
            serverDir+=dir;
           ctl_pkg_t info;
           info.type = type;

           snprintf(info.str.path, PATH_LEN,serverDir.toStdString().c_str());
   //        //info.type = event->option;

           //把包发给服务器
           Writen(ctl_sock,&info,sizeof(info));

           if(readn(ctl_sock,&reply,sizeof(int8_t)) < 0)
               perror("read");


           if(reply<0)
           {
               perror("服务器未接受到信息");
               //留着，如果错误的话图标打叉
           }
           //判断是否需要改变图标

           else if(type!=DEL_F&&type!=DEL_D)
           {
               if(fliterlist.empty()&&processlist.empty()&&isMoveIning==0)
               {
                   isUpdating=0;

               }
               if(isMoveIning==0)
               this->EmblemUpdated(QString(path1.c_str()));
           }
           emit this->setEmblemUpdated();/////带改进
        }

        if(hasUpdated==0)
        {
            hasUpdated=1;
            emit hasChanged();
        }

cout<<"update_ctl_finish"<<endl;
}

int watcher::data_update(QString filePath)
{
    cout<<"data uodating"<<endl;
    useAge=this->countSizeForDir(workDir.toStdString().c_str());
    emit this->sizeChanged(useAge);
    if(useAge>USER_SIZE)
    {
        this->setIconUpdateFailed(filePath);
        emit this->sigOverSize(filePath);
        return -1;
    }
    if(isUpdating==0&&isMoveIning==0)
    {
        isUpdating=1;
        emit this->setEmblemUpdating();
    }
    this->EmblemUpdating(filePath);
    //sleep(1);
    tsf_sock = tcp_connect(SRV_IP, SRV_DATA_PORT);
    if( tsf_sock < 0 )
        {
            perror("connect");
            return -1;
        }

    //发送PUSH请求
    uint8_t request = DATA_PUSH;
    if( write(tsf_sock,&request,sizeof(uint8_t)) < 0 )
    {
        perror("send request to 1235");
        ::close(tsf_sock);
        return -1;
    }

    //发送用户名
    char usr_name[USR_LEN];
    strncpy(usr_name,userName.c_str(),USR_LEN);
    if( writen(tsf_sock,usr_name,USR_LEN) < 0)
    {
        perror("send usr_name to 1235");
        ::close(tsf_sock);
        return -1;
    }

    //生成服务器路径
    char serverPath[PATH_LEN];
    QString tmp=filePath;
    tmp.remove(workDir).prepend(QString(userName.c_str())).prepend("/gsync/");
    snprintf(serverPath,PATH_LEN,tmp.toStdString().c_str());

    //发送要更新的目录
    if(writen(tsf_sock,serverPath,PATH_LEN) < 0 )
    {
        perror("send path to 1235");
        ::close(tsf_sock);
        return -1;
    }


    int fd_temp = ::open(filePath.toStdString().c_str(),O_RDONLY);
    if( fd_temp < 0 )
    {
        cout<<"file "<<filePath.toStdString()<<" not exists now \n";
        return -1;

    }
    file_copy(tsf_sock,fd_temp);
    ctl_update(UP_F,filePath.toStdString());
    ::close(fd_temp);
    ::close(tsf_sock);

    return 0;

}
void watcher::EmblemUpdating(QString fileName)
{
    QString tmp=fileName;
    QString tmp2=workDir;
    tmp2.append("/");
    tmp.remove(tmp2);
    QStringList sList=tmp.split("/");
    tmp2=workDir;
    for(QStringList::iterator it=sList.begin();it!=sList.end();it++)
    {
        if(Running==0)
            break;
        tmp2.append("/");
        tmp2+=(*it);
        this->setIconUpdate(tmp2);
    }
}
void watcher::EmblemUpdated(QString fileName)
{
    QString tmp=fileName;
    QString tmp2=workDir;
    tmp2.append("/");
    tmp.remove(tmp2);
    QStringList sList=tmp.split("/");
    tmp2=workDir;
    for(QStringList::iterator it=sList.begin();it!=sList.end();it++)
    {
        if(Running==0)
            break;
        tmp2.append("/");
        tmp2+=(*it);
        this->setIconFinished(tmp2);
    }
}

void watcher::setIconUpdate(QString filename)
{
    filename.append("'").prepend("'");
    QString tmp="/usr/share/GeeBox/emblem "+filename+" ubuntuone-updating";
    system(tmp.toStdString().c_str());
}

//设置文件图标为更新完成
void watcher::setIconFinished(QString filename)
{
    filename.append("'").prepend("'");
    QString tmp="/usr/share/GeeBox/emblem "+filename+" ubuntuone-synchronized";
    system(tmp.toStdString().c_str());
}

void watcher::setIconUpdateFailed(QString filename)
{
    filename.append("'").prepend("'");
    QString tmp="/usr/share/GeeBox/emblem "+filename+" ubuntuone-unsynchronized";
    system(tmp.toStdString().c_str());
}

void watcher::SearchFile(QString fileName)
{
    QString tmp=fileName;
    QString tmp2=workDir;
    tmp2.append("/");
    tmp.remove(tmp2);
    QStringList sList=tmp.split("/");
    tmp2=workDir;
    for(QStringList::iterator it=sList.begin();it!=sList.end();it++)
    {
        if(Running==0)
            break;
        tmp2.append("/");
        tmp2+=(*it);
        if(updateMap.find(tmp2)!=updateMap.end())
        {
            updateMap[tmp2]++;
        }
        else
        {
            updateMap[tmp2]=1;
        }
        this->setIconUpdate(tmp2);
    }
}

void watcher::rmFromIconMap(QString fileName)
{
    QString tmp=fileName;
    QString tmp2=workDir;
    tmp2.append("/");
    tmp.remove(tmp2);
    QStringList sList=tmp.split("/");
    tmp2=workDir;
    for(QStringList::iterator it=sList.begin();it!=sList.end();it++)
    {
        if(Running==0)
            break;
        tmp2.append("/");
        tmp2+=(*it);
        if(updateMap.find(tmp2)!=updateMap.end())
        {
            if((--updateMap[tmp2])==0)
            {
                updateMap.remove(tmp2);
                this->setIconFinished(tmp2);
            }
            else
                cout<<"dir"<<tmp2.toStdString()<<" :"<<updateMap[tmp2]<<endl;
        }
    }
}

//递归计算一个文件夹的总大小
long watcher::countSizeForDir(const char *name)
{
        long size=0;
        struct dirent *dir;
        DIR* pdir;
        struct stat buf;
        stat(name,&buf);
        size+=(int)buf.st_size;
        pdir=opendir(name);
        while((dir=readdir(pdir))!=NULL&&Running)
        {
            if(dir->d_type&DT_DIR)
            {
                if(strcmp(dir->d_name,".")==0||strcmp(dir->d_name,"..")==0)
                    continue;
                else
                {
                    char temp[256];
                    strcpy(temp,name);
                    strcat(temp,"/");
                    strcat(temp,dir->d_name);
                    size+=countSizeForDir(temp);
                }
            }
            else
            {
                    char temp[256];
                    strcpy(temp,name);
                    strcat(temp,"/");
                    strcat(temp,dir->d_name);
                    struct stat buf;
                    stat(temp,&buf);
                    size+=(long)buf.st_size;
            }
        }
        closedir(pdir);
        return size;
}

long watcher::countSizeForFile(const char *name)
{
    struct stat buf;
    stat(name,&buf);
    return (long)buf.st_size;
}

void watcher::overSize(QString name)
{

}
int& watcher::getTsf_socket()
{
    return tsf_sock;
}
void watcher::clearWatcher()
{
    this->fileToUpdate.clear();
    this->processlist.clear();
    this->fliterlist.clear();
    this->updateMap.clear();
}
